﻿/************************************************************************

   Extended Silverlight Toolkit

   Copyright (C) 2010-2012 Xceed Software Inc.

   This program is provided to you under the terms of the Microsoft Public
   License (Ms-PL) as published at http://extendedsilverlight.codeplex.com/license

   Please purchase a commercial version of this toolkit if you are using
   it in a commercial product. The commercial versions support the project,
   and also include more features for each control, priority support,
   source code, updates, removed watermark, and a proprietary license.

   Visit http://xceed.com and follow @datagrid on Twitter.

  **********************************************************************/

using System;
using Xceed.Silverlight.Data.Stats;

namespace Xceed.Silverlight.Data
{
  public abstract class SyncDataSourceProvider : DataSourceProvider
  {
    #region Static Fields

    private static readonly Guid ExecuteCountQueryCallId = DataUtils.CreateCallId();
    private static readonly Guid ExecuteDataQueryCallId = DataUtils.CreateCallId();
    private static readonly Guid ExecuteGroupCountQueryCallId = DataUtils.CreateCallId();
    private static readonly Guid ExecuteStatQueryCallId = DataUtils.CreateCallId();

    #endregion

    #region Constructor

    protected SyncDataSourceProvider()
      : base()
    {
    }

    #endregion

    #region CanFilter Property

    public override bool CanFilter
    {
      get
      {
        return true;
      }
    }

    #endregion

    #region CanSkip Property

    public override bool CanSkip
    {
      get
      {
        return true;
      }
    }

    #endregion

    #region CanSort Property

    internal override sealed bool CanSort
    {
      get
      {
        return true;
      }
    }

    #endregion

    #region IsAsynchronous Property

    internal sealed override bool IsAsynchronous
    {
      get
      {
        return false;
      }
    }

    #endregion

    #region IsCachingAllowed Property

    internal override bool IsCachingAllowed
    {
      get
      {
        return false;
      }
    }

    #endregion

    #region IsBufferingAllowed Property

    internal override bool IsBufferingAllowed
    {
      get
      {
        return false;
      }
    }

    #endregion

    protected abstract CountQueryResult ExecuteCountQuery( CountQueryParameters queryParameters );

    protected abstract DataQueryResult ExecuteDataQuery( DataQueryParameters queryParameters );

    protected abstract GroupCountQueryResult ExecuteGroupCountQuery( GroupCountQueryParameters queryParameters );

    protected abstract StatQueryResult ExecuteStatQuery( StatQueryParameters queryParameters );

    internal override IAsyncResult BeginExecuteCountQueryCore(
      CountQueryParameters queryParameters,
      AsyncCallback callback,
      object state )
    {
      CountQueryResult queryResult = this.ExecuteCountQuery( queryParameters );
      AsyncResult asyncResult = new AsyncResult( 
                                  SyncDataSourceProvider.ExecuteCountQueryCallId, 
                                  callback, 
                                  state );

      asyncResult.StartSync( queryResult );

      return asyncResult;
    }

    internal override CountQueryResult EndExecuteCountQueryCore( IAsyncResult asyncResult )
    {
      asyncResult.ValidateCallEnd( SyncDataSourceProvider.ExecuteCountQueryCallId );

      return asyncResult.GetCallResult<CountQueryResult>();
    }

    internal override IAsyncResult BeginExecuteDataQueryCore(
      DataQueryParameters queryParameters,
      AsyncCallback callback,
      object state )
    {
      DataQueryResult queryResult = this.ExecuteDataQuery( queryParameters );
      AsyncResult asyncResult = new AsyncResult(
                                  SyncDataSourceProvider.ExecuteDataQueryCallId,
                                  callback,
                                  state );

      asyncResult.StartSync( queryResult );

      return asyncResult;
    }

    internal override DataQueryResult EndExecuteDataQueryCore( IAsyncResult asyncResult )
    {
      asyncResult.ValidateCallEnd( SyncDataSourceProvider.ExecuteDataQueryCallId );

      return asyncResult.GetCallResult<DataQueryResult>();
    }

    internal override IAsyncResult BeginExecuteGroupCountQueryCore( GroupCountQueryParameters queryParameters, AsyncCallback callback, object state )
    {
      GroupCountQueryResult queryResult = this.ExecuteGroupCountQuery( queryParameters );
      AsyncResult asyncResult = new AsyncResult(
                                  SyncDataSourceProvider.ExecuteGroupCountQueryCallId,
                                  callback,
                                  state );

      asyncResult.StartSync( queryResult );

      return asyncResult;
    }

    internal override GroupCountQueryResult EndExecuteGroupCountQueryCore( IAsyncResult asyncResult )
    {
      asyncResult.ValidateCallEnd( SyncDataSourceProvider.ExecuteGroupCountQueryCallId );

      return asyncResult.GetCallResult<GroupCountQueryResult>();
    }

    internal override IAsyncResult BeginExecuteStatQueryCore(
      StatQueryParameters queryParameters,
      AsyncCallback callback,
      object state )
    {
      StatQueryResult queryResult;

      try
      {
        queryResult = this.ExecuteStatQuery( queryParameters );
      }
      catch( Exception e )
      {
        queryResult = new StatQueryResult( new StatResult( e ) );
      }

      AsyncResult asyncResult = new AsyncResult(
                                  SyncDataSourceProvider.ExecuteStatQueryCallId,
                                  callback,
                                  state );

      asyncResult.StartSync( queryResult );

      return asyncResult;
    }

    internal override StatQueryResult EndExecuteStatQueryCore( IAsyncResult asyncResult )
    {
      asyncResult.ValidateCallEnd( SyncDataSourceProvider.ExecuteStatQueryCallId );

      return asyncResult.GetCallResult<StatQueryResult>();
    }
  }
}
